static { // Pull in the actual implementation of the policy at run-time try { Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME); sPolicy = (IPolicy)policyClass.newInstance(); } catch (ClassNotFoundException ex) { thrownew RuntimeException( POLICY_IMPL_CLASS_NAME + " could not be loaded", ex); } catch (InstantiationException ex) { thrownew RuntimeException( POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex); } catch (IllegalAccessException ex) { thrownew RuntimeException( POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex); } }
// Cannot instantiate this class privatePolicyManager(){}
// The static methods to spawn new policy-specific objects publicstatic Window makeNewWindow(Context context){ return sPolicy.makeNewWindow(context); }
static { // For performance reasons, preload some policy specific classes when // the policy gets loaded. for (String s : preload_classes) { try { Class.forName(s); } catch (ClassNotFoundException ex) { Log.e(TAG, "Could not preload class for phone policy: " + s); } } }
public Window makeNewWindow(Context context){ returnnew PhoneWindow(context); }
public LayoutInflater makeNewLayoutInflater(Context context){ returnnew PhoneLayoutInflater(context); }
public WindowManagerPolicy makeNewWindowManager(){ returnnew PhoneWindowManager(); }
public FallbackEventHandler makeNewFallbackEventHandler(Context context){ returnnew PhoneFallbackEventHandler(context); } }
publicbooleandispatchTouchEvent(MotionEvent event){ boolean result = false;
if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onTouchEvent(event, 0); }
finalint actionMasked = event.getActionMasked(); if (actionMasked == MotionEvent.ACTION_DOWN) { // Defensive cleanup for new gesture stopNestedScroll(); }
if (onFilterTouchEventForSecurity(event)) { // 如果存在mOnTouchListener,直接交给它消费Touch事件 ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { result = true; }
// 交给onTouchEvent()方法消费Touch事件 if (!result && onTouchEvent(event)) { result = true; } }
if (!result && mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); }
// Clean up after nested scrolls if this is the end of a gesture; // also cancel it if we tried an ACTION_DOWN but we didn't want the rest // of the gesture. if (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL || (actionMasked == MotionEvent.ACTION_DOWN && !result)) { stopNestedScroll(); }
publicbooleanonTouchEvent(MotionEvent event){ finalfloat x = event.getX(); finalfloat y = event.getY(); finalint viewFlags = mViewFlags;
if ((viewFlags & ENABLED_MASK) == DISABLED) { if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { setPressed(false); } // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); }
if (mTouchDelegate != null) { if (mTouchDelegate.onTouchEvent(event)) { returntrue; } }
if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { switch (event.getAction()) { case MotionEvent.ACTION_UP: boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { // take focus if we don't have it already and we should in // touch mode. boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); }
if (prepressed) { // The button is being released before we actually // showed it as pressed. Make it show the pressed // state now (before scheduling the click) to ensure // the user sees it. setPressed(true, x, y); }
if (!mHasPerformedLongPress) { // This is a tap, so remove the longpress check removeLongPressCallback();
// Only perform take click actions if we were in the pressed state if (!focusTaken) { // Use a Runnable and post this rather than calling // performClick directly. This lets other visual state // of the view update before click actions start. if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { //关键点 performClick(); } } }
if (mUnsetPressedState == null) { mUnsetPressedState = new UnsetPressedState(); }
if (prepressed) { postDelayed(mUnsetPressedState, ViewConfiguration.getPressedStateDuration()); } elseif (!post(mUnsetPressedState)) { // If the post failed, unpress right now mUnsetPressedState.run(); }
removeTapCallback(); } break;
case MotionEvent.ACTION_DOWN: mHasPerformedLongPress = false;
if (performButtonActionOnTouchDown(event)) { break; }
// Walk up the hierarchy to determine if we're inside a scrolling container. boolean isInScrollingContainer = isInScrollingContainer();
// For views inside a scrolling container, delay the pressed feedback for // a short period in case this is a scroll. if (isInScrollingContainer) { mPrivateFlags |= PFLAG_PREPRESSED; if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } mPendingCheckForTap.x = event.getX(); mPendingCheckForTap.y = event.getY(); postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); } else { // Not inside a scrolling container, so show the feedback right away setPressed(true, x, y); checkForLongClick(0); } break;
case MotionEvent.ACTION_CANCEL: setPressed(false); removeTapCallback(); removeLongPressCallback(); break;
case MotionEvent.ACTION_MOVE: drawableHotspotChanged(x, y);
// Be lenient about moving outside of buttons if (!pointInView(x, y, mTouchSlop)) { // Outside button removeTapCallback(); if ((mPrivateFlags & PFLAG_PRESSED) != 0) { // Remove any future long press/tap checks removeLongPressCallback();
publicbooleanperformClick(){ finalboolean result; final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); //通知回调mOnClickListener的onClick方法 li.mOnClickListener.onClick(this); result = true; } else { result = false; }